package com.weilele.mvvm.base.helper

import android.util.SparseArray
import androidx.core.util.forEach
import com.weilele.mvvm.utils.vLaout.MvvmRcvAdapter
import com.weilele.mvvm.utils.vLaout.MvvmRcvListAdapter

/**
 * 分页帮助类，有需求再慢慢完善
 */
/**
 * 创建观察对象
 */
fun <T, H : PageHelper<T>> createPageHelperData() = createStatusLiveData<H>()

/**
 * 创建默认的，类型为pageHelper
 */
fun <T> pageHelperData() = createPageHelperData<T, PageHelper<T>>()

/**
 * 更新数据
 */
inline fun <T, reified H : PageHelper<T>> StatusMutableLiveData<H>.updatePageHelper(
    pageIndex: Int,/*当前是第几页*/
    datas: MutableList<T>?,/*当前的页面的集合*/
    isFirstPage: Boolean,/*是否是第一页*/
    hasNextPage: Boolean?,/*是否有下一页（即是否是最后一页）*/
    pageTotalCount: Int?,/*可以加载的总数*/
    pageData: Any? = null,/*当前页面的数据*/
    helper: H? = null,
): H {
    var pageHelper = helper ?: this.data
    if (pageHelper == null) {
        pageHelper = H::class.java.newInstance()
    }
    pageHelper!!.updatePageValue(
        pageIndex,
        datas,
        isFirstPage,
        hasNextPage,
        pageTotalCount,
        pageData
    )
    return pageHelper
}

open class PageHelper<T> {
    //记录每一页的数据集合，总是按照key的大小排序，key为当前页数
    private val _datasMap = SparseArray<MutableList<T>?>()

    //记录每一页的数据,总是按照key的大小排序，key为当前页数
    private val _pageMap = SparseArray<Any?>()
    private var _isFirstPage = true
    private var _hasNextPage = true
    private var _totalSize = 0
    private var _pageIndex = 0

    /**
     * 是否是第一页
     */
    val isFirstPage: Boolean
        get() = _isFirstPage

    /**
     * 当前页面
     */
    val currentPageIndex: Int
        get() = _pageIndex

    /**
     * 总数
     */
    val totalSize: Int
        get() = _totalSize

    /**
     * 是否还有下一页
     */
    val hasNextPage: Boolean
        get() = _hasNextPage

    /**
     * 是否还有上一页
     * 如果不是第一页，就还有上一页
     */
    val hasPrePage: Boolean
        get() = !isFirstPage

    /**
     * 当前页面数据
     */
    val currentPageData: Any?
        get() = getPageData(currentPageIndex)

    /**
     * 当前页面集合
     */
    val currentPageList: MutableList<T>?
        get() = getPageList(currentPageIndex)

    /**
     * 当前总集合的数量
     */
    val currentTotalCount: Int
        get() {
            var count = 0
            _datasMap.forEach { _, value ->
                value?.count()?.let {
                    count += it
                }
            }
            return count
        }

    val totalLoadedDatas: MutableList<T>
        get() {
            val newDatas = mutableListOf<T>()
            _datasMap.forEach { key, value ->
                value?.let {
                    newDatas.addAll(it)
                }
            }
            return newDatas
        }

    /**
     * 获取当前页面数据
     */
    fun getPageData(index: Int) = _pageMap[index]

    /**
     * 获取当前页面集合
     */
    fun getPageList(index: Int) = _datasMap[index]

    /**
     * hasNextPage 和 pageTotal 二选一，两个都有，则以hasNextPage为准
     * isClearOld：是否清除旧数据，针对那种页面展示固定数据，页数可以随意变更（不是按照顺序分页加载的情况）
     */
    fun updatePageValue(
        pageIndex: Int,/*当前是第几页*/
        datas: MutableList<T>?,/*当前的页面的集合*/
        isFirstPage: Boolean,/*是否是第一页*/
        hasNextPage: Boolean?,/*是否有下一页（即是否是最后一页）*/
        pageTotalCount: Int?,/*可以加载的总数*/
        pageData: Any? = null,/*当前页面的数据*/
    ) {
        //当前索引
        _pageIndex = pageIndex
        //是否第一页
        _isFirstPage = isFirstPage
        //总数
        _totalSize = pageTotalCount ?: 0
        //是否有下一页
        _hasNextPage = if (hasNextPage == null) {
            val newCount = datas?.count() ?: 0
            currentTotalCount + newCount < totalSize
        } else {
            hasNextPage
        }
        pageData?.let {
            _pageMap.put(pageIndex, it)
        }
        _datasMap.put(pageIndex, datas)
    }


    /**
     * 刷新集合,异步比较
     */
    fun refreshAdapter(
        adapter: MvvmRcvListAdapter<Any, *>,
        /*展示某一页的数据，为null，则展示所有的,默认逻辑，第一页只展示第一页数据，否则展示所有数据*/
        pageIndex: Int? = null,
        appendData: Any? = null,
        isAddAllAppendData: Boolean = false
    ) {
        adapter.refresh(getRefreshData(pageIndex, appendData, isAddAllAppendData))
    }

    /**
     * 刷新集合,同步比较
     */
    fun refreshAdapter(
        adapter: MvvmRcvAdapter<Any, *>,
        /*展示某一页的数据，为null，则展示所有的,默认逻辑，第一页只展示第一页数据，否则展示所有数据*/
        pageIndex: Int? = null,
        appendData: Any? = null,
        isAddAllAppendData: Boolean = false,
        areItemTheSame: ((old: Any?, new: Any?) -> Boolean)? = null,
        areContentsTheSame: ((old: Any?, new: Any?) -> Boolean)? = null
    ) {
        adapter.refresh(
            getRefreshData(pageIndex, appendData, isAddAllAppendData),
            areItemTheSame,
            areContentsTheSame
        )
    }

    /**
     * 获取刷新的数据
     */
    private fun getRefreshData(
        pageIndex: Int? = if (isFirstPage) currentPageIndex else null,
        appendData: Any?,
        isAddAllAppendData: Boolean
    ): MutableList<Any> {
        val index = pageIndex ?: -1
        //用新的集合，防止刷新破换原集合
        val newDatas = if (index >= 0) {
            _datasMap[index]?.toMutableList() ?: mutableListOf()
        } else {
            totalLoadedDatas
        }
        val refeshData: MutableList<Any> = if (appendData != null) {
            val list = mutableListOf<Any>()
            list.addAll(newDatas as MutableList<Any>)
            if (isAddAllAppendData && appendData is MutableList<*>) {
                list.addAll(appendData as MutableList<Any>)
            } else {
                list.add(appendData)
            }
            list
        } else {
            newDatas as MutableList<Any>
        }
        return refeshData
    }

    /**
     * 设置滚动到底部监听
     */
    fun setOnListScrollEndListener(adapter: MvvmRcvAdapter<Any, *>, call: Function0<Unit>) {
        adapter.setOnScrollEndListener {
            if (hasNextPage) {
                call.invoke()
            }
        }
    }

    fun setOnListScrollEndListener(adapter: MvvmRcvListAdapter<Any, *>, call: Function0<Unit>) {
        adapter.setOnScrollEndListener {
            if (hasNextPage) {
                call.invoke()
            }
        }
    }
}